// 引用部分
import gulp, { lastRun } from 'gulp';
import include from 'gulp-file-include';
import htmlmin from 'gulp-htmlmin';
import del from 'delete';
import cleanCSS from 'gulp-clean-css';
import * as dartSass from 'sass';
import gulpSass from 'gulp-sass';
import sourcemaps from 'gulp-sourcemaps';
import uglify from 'gulp-uglify';
import rev from 'gulp-rev';
import revCollector from 'gulp-rev-collector';
import connect from 'gulp-connect';
import imagemin, { gifsicle, mozjpeg, optipng, svgo } from 'gulp-imagemin';
import chinese2unicode from 'gulp-chinese2unicode';
import dotenv from 'dotenv';

// 组合 sass 编译器
const proceSass = gulpSass(dartSass);

dotenv.config();
console.log('当前环境：', process.env.NODE_ENV);

/**
 * 启动实时刷新服务
 */
function connectServer(cb) {
  connect.server({
    root: './dist',
    livereload: true,
    port: 8040,
  });
  cb();
}

/**
 * 监听任务
 */
function watcher(cb) {
  const baseDelay = 300;

  gulp.watch(
    './src/**/*.html',
    { delay: baseDelay },
    gulp.series(revHTML_index, revHTML_child),
  );
  gulp.watch(
    './src/styles/**/*.scss',
    { delay: baseDelay },
    gulp.series(procSCSS, revHTML_index, revHTML_child),
  );
  gulp.watch(
    './src/scripts/**/*.js',
    { delay: baseDelay },
    gulp.series(
      procModulesScript,
      procJavaScript,
      revJS,
      revHTML_index,
      revHTML_child,
    ),
  );
  cb();
}

/**
 * 处理 scss 文件
 */
function procSCSS() {
  return gulp
    .src('./src/styles/**/*.scss')
    .pipe(sourcemaps.init())
    .pipe(rev())
    .pipe(proceSass())
    .pipe(sourcemaps.write())
    .pipe(gulp.dest('./dist/styles'))
    .pipe(rev.manifest())
    .pipe(gulp.dest('./release/rev/css'))
    .pipe(connect.reload());
}

/**
 * 压缩处理上线前的 css 文件
 */
function procCSS_min() {
  return gulp
    .src('./dist/styles/**/*.css')
    .pipe(
      cleanCSS({
        compatibility: '*',
        level: {
          2: {
            removeUnusedAtRules: false,
          },
        },
      }),
    )
    .pipe(gulp.dest('./dist/styles'));
}

/**
 * 修改 css 文件内的图片路径为 MD5 码路径
 */
function revCSS() {
  return gulp
    .src(['./release/rev/image/*.json', './dist/styles/*.css'])
    .pipe(
      revCollector({
        replaceReved: true,
      }),
    )
    .pipe(gulp.dest('./dist/styles'));
}

/**
 * 处理 js 文件
 */
function procJavaScript() {
  return gulp
    .src('./src/scripts/*.js')
    .pipe(sourcemaps.init())
    .pipe(rev())
    .pipe(sourcemaps.write())
    .pipe(gulp.dest('./dist/scripts'))
    .pipe(rev.manifest())
    .pipe(gulp.dest('./release/rev/js'))
    .pipe(connect.reload());
}

/**
 * 处理插件
 */
function procPluginsScript() {
  return gulp
    .src('./src/plugins/*.js')
    .pipe(gulp.dest('./dist/plugins'))
    .pipe(connect.reload());
}

/**
 * 处理模块脚本文件
 */
function procModulesScript() {
  return gulp
    .src('./src/scripts/utils/*.js')
    .pipe(sourcemaps.init())
    .pipe(rev())
    .pipe(sourcemaps.write())
    .pipe(gulp.dest('./dist/scripts/utils'))
    .pipe(rev.manifest())
    .pipe(gulp.dest('./release/rev/js/utils'))
    .pipe(connect.reload());
}

/**
 * 处理 MD5 改名后的 JS 文件
 */
function revJS() {
  return gulp
    .src(['./release/rev/js/**/*.json', './dist/scripts/**/*.js'])
    .pipe(
      revCollector({
        replaceReved: true,
      }),
    )
    .pipe(gulp.dest('./dist/scripts'));
}

/**
 * 压缩处理上线前的 plugins 里的 js 文件
 */
function procPluginsJS_min() {
  return gulp
    .src('./dist/plugins/**/*.js')
    .pipe(uglify())
    .pipe(gulp.dest('./dist/plugins'));
}

/**
 * 压缩处理上线前的 js 文件
 */
function procJavaScript_min() {
  return gulp
    .src('./dist/scripts/**/*.js')
    .pipe(uglify())
    .pipe(gulp.dest('./dist/scripts'));
}

/**
 * 将 js 文件内的中文进行 Unicode 编码
 */
function procJavaScript_unicode(cb) {
  cb();

  return gulp
    .src('./dist/scripts/**/*.js', {
      allowEmpty: true,
    })
    .pipe(chinese2unicode('UTF-8'))
    .pipe(gulp.dest('./dist/scripts'));
}

/**
 * 处理主页 html 文件
 */
function revHTML_index() {
  return gulp
    .src(['./release/rev/**/*.json', './src/*.html'])
    .pipe(
      include({
        prefix: '@@',
      }),
    )
    .pipe(
      revCollector({
        replaceReved: true,
      }),
    )
    .pipe(gulp.dest('./dist'))
    .pipe(connect.reload());
}

/**
 * 处理其他页面 html 文件
 */
function revHTML_child() {
  return gulp
    .src(['./release/rev/**/*.json', './src/pages/*.html'])
    .pipe(
      include({
        prefix: '@@',
      }),
    )
    .pipe(
      revCollector({
        replaceReved: true,
      }),
    )
    .pipe(gulp.dest('./dist/pages'))
    .pipe(connect.reload());
}

/**
 * 压缩处理上线前的 html 文件
 */
function procHTML_min() {
  return gulp
    .src('./dist/**/*.html')
    .pipe(
      htmlmin({
        collapseWhitespace: true, // 是否去掉空格
        removeComments: true, // 是否去掉注释
        minifyCSS: true, // 是否压缩HTML里面的CSS
        minifyJS: true, // 是否压缩HTML里面的JS
      }),
    )
    .pipe(gulp.dest('dist'));
}

/**
 * 简单的转移图片到发布的目录
 */
function moveImages(done) {
  return gulp
    .src('./src/images/**/*', {
      encoding: false,
      since: lastRun(moveImages),
    })
    .pipe(gulp.dest('./dist/images'), done);
}

/**
 * 简单的转移 favicon 到发布的目录
 */
function moveFavicon() {
  return gulp
    .src('./src/favicon.ico', { encoding: false })
    .pipe(gulp.dest('./dist'));
}

/**
 * 用于在构建上线版本时压缩图片
 */
function miniImages() {
  return gulp
    .src('./src/images/**/*', {
      encoding: false,
      since: lastRun(miniImages),
    })
    .pipe(rev())
    .pipe(
      imagemin([
        gifsicle({ interlaced: true }),
        mozjpeg({ quality: 65, progressive: true }),
        optipng({ optimizationLevel: 3 }),
        svgo({
          plugins: [
            {
              name: 'removeViewBox',
              active: true,
            },
            {
              name: 'cleanupIDs',
              active: false,
            },
          ],
        }),
      ]),
    )
    .pipe(gulp.dest('./dist/images'))
    .pipe(rev.manifest())
    .pipe(gulp.dest('./release/rev/image'));
}

/**
 * 删除构建打包文件
 */
function delFile(cb) {
  return del(['./dist', './release'], cb);
}

/**** 主要命令输出部分 ****/
function defaultTask(cb) {
  return gulp.series(
    delFile,
    gulp.parallel(
      procSCSS,
      procPluginsScript,
      procModulesScript,
      procJavaScript,
      moveImages,
      moveFavicon,
    ),
    revJS,
    revHTML_index,
    revHTML_child,
    gulp.parallel(watcher, connectServer),
  )(cb);
}

function buildTask(cb) {
  gulp.series(
    delFile,
    gulp.parallel(
      procSCSS,
      procPluginsScript,
      procModulesScript,
      procJavaScript,
      moveFavicon,
    ),
    miniImages,
    revCSS,
    revJS,
    revHTML_index,
    revHTML_child,
    gulp.parallel(
      procCSS_min,
      procPluginsJS_min,
      procJavaScript_min,
      procHTML_min,
    ),
    procJavaScript_unicode,
  )(cb);
}

// 默认构建任务
export default defaultTask;

// 构建完整上线版本
export const build = buildTask;

/**** 其他命令输出部分 ****/

// 删除文件命令
export const deleteFile = gulp.series(delFile);
// 转移图片部分
export const moveImgToDist = gulp.series(moveImages, moveFavicon);
